package cz.acies.data.persist;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

public class TreeNode implements Serializable, JsonSerializer<TreeNode>
{
	private static final long serialVersionUID = 778193821307902866L;

	private String id; 
	private String text;
	private String iconCls;
	private List<TreeNode> children;
	private Map<String, Object> attributes;

	public TreeNode() {
		this(null, null);
	}

	public TreeNode(String id, String text) {
		this.id = id;
		this.text = text;
		children = new ArrayList<TreeNode>();
		attributes = new HashMap<String, Object>();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getText() {
		return text;
	}
	
	public void setText(String label) {
		this.text = label;
	}

	public String getIconCls() {
		return iconCls;
	}
	
	public void setIconCls(String image) {
		this.iconCls = image;
	}
	
	// -----  -----------------------------------------------------------------

	public TreeNode addChild(TreeNode child) {
		this.children.add(child);
		return this;
	}
	
	public void removeChild(TreeNode child) {
		this.children.remove(child);
	}
	
	public List<TreeNode> getChildren() {
		return children;
	}

	public boolean hasChildren() {
		return this.children.size() > 0;
	}
	
	public void setChildren(List<TreeNode> children) {
		this.children = children;
	}

	// -----  -----------------------------------------------------------------
	
	public Map<String, Object> getAttributes() {
		return attributes;
	}

	public TreeNode setAttributes(Map<String, Object> attributes) {
		this.attributes = attributes;
		return this;
	}

	public TreeNode setAttribute(String key, Object value) {
		attributes.put(key, value);
		return this;
	}
	
	// -----  ----------------------------------------------------------------
	
	public Map<String, Object> toJson() {
		Map<String, Object> data = new LinkedHashMap<String, Object>();
		try {
			data.put("id", this.getId());
			data.put("text", this.getText());
			data.put("iconCls", this.getIconCls());
			data.put("attributes", this.getAttributes());
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			for (TreeNode child : this.getChildren()) {
				Map<String, Object> map = child.toJson();
				list.add(map);
			}					
			data.put("children", list);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}

	@Override
	public JsonElement serialize(TreeNode node, Type type, JsonSerializationContext context) {
		Gson gson = new Gson();
		final JsonObject json = new JsonObject();
		json.addProperty("id", node.getId());
		json.addProperty("text", node.getText());
		json.addProperty("iconCls", node.getIconCls());
		json.add("children", gson.toJsonTree(children, new TypeToken<List<TreeNode>>(){}.getType()));
		json.add("attributes", gson.toJsonTree(node.getAttributes(), new TypeToken<Map<String, Object>>() {}.getType()));
		return json;
	}

}
